home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / utility / ffe101.zip / GRAPH.SWG / 0013_PCX EXPLANATION.pas < prev    next >
Pascal/Delphi Source File  |  1996-09-04  |  24KB  |  588 lines

  1.  
  2. ZSoft PCX File Format Technical Reference Manual
  3.  
  4.  
  5. Introduction                            2
  6. Image  File (.PCX) Format               3
  7. ZSoft .PCX FILE HEADER FORMAT           4
  8. Decoding .PCX Files                     6
  9. Palette Information Description         7
  10. EGA/VGA 16 Color Palette Information    7
  11. VGA 256 Color Palette Information       7
  12. 24-Bit .PCX Files                       8
  13. CGA Color Palette Information           8
  14. CGA Color Map                           8
  15. PC Paintbrush Bitmap Character Format   9
  16. Sample "C" Routines                    10
  17. FRIEZE Technical Information           14
  18. General FRIEZE Information             14
  19. 7.00 and Later FRIEZE                  14
  20. FRIEZE Function Calls                  15
  21. FRIEZE Error Codes                     18
  22.  
  23.  
  24. Introduction
  25.  
  26. This  booklet was designed to aid  developers and users in understanding
  27. the technical aspects of the .PCX file format and the use of FRIEZE. Any
  28. comments, questions or suggestions about this booklet should be sent to:
  29.  
  30.         ZSoft Corporation
  31.         Technical Services
  32.         ATTN: Code Librarian
  33.         450 Franklin Rd. Suite 100
  34.         Marietta, GA  30067
  35.  
  36.  
  37. Technical Reference Manual information compiled by:
  38. Dean Ansley
  39.  
  40. Revision 5
  41.  
  42. To  down load additional information and the source for a complete Turbo
  43. Pascal  program  to show .PCX files  on  a CGA/EGA/VGA graphics display,
  44. call  our BBS at (404)427-1045. You may use  a 9600 baud modem or a 2400
  45. baud  standard  modem. Your modem should be  set for 8 data bits, 1 stop
  46. bit, and NO parity.
  47.  
  48. Image  File (.PCX) Format
  49.  
  50. If  you  have  technical  questions on  the  format,  please do not call
  51. technical  support.  ZSoft provides this document  as  a courtesy to its
  52. users  and  developers. It is not  the  function of Technical Support to
  53. provide  programming  assistance.  If something  is  not  clear, leave a
  54. message  on  our  BBS,  Compuserve, or write  us  a  letter at the above
  55. address.
  56.  
  57. The  information  in this section will be  useful if you want to write a
  58. program  to  read  or write PCX files  (images).  If you want to write a
  59. special  case program for one particular image format you should be able
  60. to  produce  something that runs twice as  fast  as "Load from..." in PC
  61. Paintbrush.
  62.  
  63. Image  files used by PC Paintbrush product family and FRIEZE (those with
  64. a  .PCX extension) begin with a 128  byte header. Usually you can ignore
  65. this  header,  since  your  images  will  probably  all  have  the  same
  66. resolution.  If you want to process different resolutions or colors, you
  67. will  need to interpret the header correctly. The remainder of the image
  68. file  consists of encoded graphic data.  The encoding method is a simple
  69. byte  oriented run-length technique. We reserve the right to change this
  70. method  to  improve space efficiency. When  more than one color plane is
  71. stored  in  the  file, each line of  the  image is stored by color plane
  72. (generally ordered red, green, blue, intensity), As shown below.
  73.  
  74. Scan line 0:         RRR...        (Plane 0)
  75.                      GGG...        (Plane 1)
  76.                      BBB...        (Plane 2)
  77.                      III...        (Plane 3)
  78. Scan line 1:         RRR...
  79.                      GGG...
  80.                      BBB...
  81.                      III...        (etc.)
  82.  
  83. The encoding method is:
  84.     FOR  each  byte,  X,  read from the file
  85.         IF the top two bits of X are  1's then
  86.             count = 6 lowest bits of X
  87.             data = next byte following X
  88.         ELSE
  89.             count = 1
  90.             data = X
  91.  
  92. Since  the  overhead this technique requires  is, on average, 25% of the
  93. non-repeating  data and is at least  offset whenever bytes are repeated,
  94. the file storage savings are usually considerable.
  95.  
  96. ZSoft .PCX FILE HEADER FORMAT
  97.  
  98. Byte      Item          Size   Description/Comments
  99.  0         Manufacturer 1      Constant Flag, 10 = ZSoft .pcx
  100.  1         Version      1      Version information
  101.                                0 = Version 2.5 of PC Paintbrush
  102.                                2 = Version 2.8 w/palette information
  103.                                3 = Version 2.8 w/o palette information
  104.                                4 = PC Paintbrush for Windows(Plus for
  105.                                   Windows uses Ver 5)
  106.                                5 = Version 3.0 and > of PC Paintbrush
  107.                                   and PC Paintbrush +, includes
  108.                                   Publisher's Paintbrush . Includes
  109.                                   24-bit .PCX files
  110.  2         Encoding      1     1 = .PCX run length encoding
  111.  3         BitsPerPixel  1     Number of bits to represent a pixel
  112.                                   (per Plane) - 1, 2, 4, or 8
  113.  4         Window        8     Image Dimensions: Xmin,Ymin,Xmax,Ymax
  114. 12         HDpi          2     Horizontal Resolution of image in DPI*
  115. 14         VDpi          2     Vertical Resolution of image in DPI*
  116. 16         Colormap     48     Color palette setting, see text
  117. 64         Reserved      1     Should be set to 0.
  118. 65         NPlanes       1     Number of color planes
  119. 66         BytesPerLine  2     Number of bytes to allocate for a scanline
  120.                                   plane.  MUST be an EVEN number.  Do NOT
  121.                                   calculate from Xmax-Xmin.
  122. 68         PaletteInfo   2     How to interpret palette- 1 = Color/BW,
  123.                                   2 = Grayscale (ignored in PB IV/ IV +)
  124. 70         HscreenSize   2     Horizontal screen size in pixels. New field
  125.                                   found only in PB IV/IV Plus
  126. 72         VscreenSize   2     Vertical screen size in pixels. New field
  127.                                   found only in PB IV/IV Plus
  128. 74         Filler       54     Blank to fill out 128 byte header.  Set all
  129.                                   bytes to 0
  130.  
  131. NOTES:
  132.  
  133. All sizes are measured in BYTES.
  134.  
  135. All variables of SIZE 2 are integers.
  136.  
  137. *HDpi  and VDpi represent the  Horizontal and Vertical resolutions which
  138. the  image was created (either printer  or scanner); i.e. an image which
  139. was scanned might have 300 and 300 in each of these fields.
  140.  
  141. Decoding .PCX Files
  142.  
  143. First,  find  the pixel dimensions of  the image by calculating [XSIZE =
  144. Xmax  - Xmin + 1] and [YSIZE = Ymax - Ymin + 1]. Then calculate how many
  145. bytes are required to hold one complete uncompressed scan line:
  146.  
  147. TotalBytes = NPlanes * BytesPerLine
  148.  
  149. Note  that since there are always an even number of bytes per scan line,
  150. there  will  probably  be  unused data at  the  end  of  each scan line.
  151. TotalBytes  shows how much storage must be available to decode each scan
  152. line,  including any blank area on the  right side of the image. You can
  153. now  begin  decoding the first scan line  -  read the first byte of data
  154. from  the  file. If the top two bits  are set, the remaining six bits in
  155. the  byte show how many times to duplicate the next byte in the file. If
  156. the  top two bits are not set, the first byte is the data itself, with a
  157. count of one.
  158.  
  159. Continue  decoding the rest of the line.  Keep a running subtotal of how
  160. many  bytes  are moved and duplicated  into  the output buffer. When the
  161. subtotal  equals  TotalBytes,  the scan  line  is complete. There should
  162. always  be a decoding break at the end of each scan line. But there will
  163. not  be a decoding break at the end of each plane within each scan line.
  164. When  the  scan line is completed, there  may be extra blank data at the
  165. end  of each plane within the scan  line. Use the XSIZE and YSIZE values
  166. to  find  where  the valid image data  is.  If  the data is multi-plane,
  167. BytesPerLine shows where each plane ends within the scan line.
  168.  
  169. Continue  decoding the remainder of the scan  lines (do not just read to
  170. end-of-file).  There  may be additional data  after the end of the image
  171. (palette, etc.)
  172.  
  173. Palette Information Description
  174.  
  175. EGA/VGA 16 Color Palette Information
  176.  
  177. In  standard  RGB  format (IBM EGA, IBM  VGA)  the  data is stored as 16
  178. triples.  Each  triple is a 3 byte  quantity of Red, Green, Blue values.
  179. The  values  can  range  from  0-255,  so  some  interpretation  may  be
  180. necessary.  On  an IBM EGA, for example,  there are 4 possible levels of
  181. RGB  for  each color. Since 256/4 = 64,  the  following is a list of the
  182. settings and levels:
  183.  
  184. Setting                Level
  185.    0-63                0
  186.  64-127                1
  187. 128-192                2
  188. 193-254                3
  189.  
  190. VGA 256 Color Palette Information
  191.  
  192. ZSoft  has  recently added the  capability  to store palettes containing
  193. more  than  16 colors in the .PCX  image  file. The 256 color palette is
  194. formatted  and treated the same as the  16 color palette, except that it
  195. is  substantially  longer.  The palette (number  of  colors x 3 bytes in
  196. length) is appended to the end of the .PCX file, and is preceded by a 12
  197. decimal. Since the VGA device expects a palette value to be 0-63 instead
  198. of 0-255, you need to divide the values read in the palette by 4.
  199.  
  200. To access a 256 color palette:
  201.  
  202. First,  check the version number in the header; if it contains a 5 there
  203. is a palette.
  204.  
  205. Second,  read to the end of the file and count back 769 bytes. The value
  206. you  find  should be a 12 decimal,  showing  the presence of a 256 color
  207. palette.
  208.  
  209. 24-Bit .PCX Files
  210.  
  211. 24 bit images are stored as version 5 or above as 8 bit, 3 plane images.
  212.  
  213. 24 bit images do not contain a palette.
  214.  
  215. Bit planes are ordered as lines of red, green, blue in that order.
  216.  
  217. CGA Color Palette Information
  218.  
  219. NOTE: This is no longer supported for PC Paintbrush IV/IV Plus.
  220.  
  221. For  a  standard  IBM  CGA board, the  palette  settings  are a bit more
  222. complex. Only the first byte of the triple is used. The first triple has
  223. a  valid  first byte which represents  the background color. To find the
  224. background,  take the (unsigned) byte value  and divide by 16. This will
  225. give  a  result  between 0-15, hence  the  background  color. The second
  226. triple  has a valid first byte, which represents the foreground palette.
  227. PC  Paintbrush supports 8 possible CGA  palettes, so when the foreground
  228. setting  is encoded between 0 and 255, there are 8 ranges of numbers and
  229. the divisor is 32.
  230.  
  231. CGA Color Map
  232.  
  233. Header Byte #16
  234.  
  235. Background color is determined in the upper four bits.
  236.  
  237. Header Byte #19
  238.  
  239. Only  upper  3 bits are used, lower  5 bits are ignored. The first three
  240. bits  that  are used are ordered C,  P, I. These bits are interpreted as
  241. follows:
  242.  
  243. c: color burst enable - 0 = color; 1 = monochrome
  244.  
  245. p: palette - 0 = yellow; 1 = white
  246.  
  247. i: intensity - 0 = dim; 1 = bright
  248.  
  249. PC Paintbrush Bitmap Character Format
  250.  
  251. NOTE:  This  format  is  for  PC Paintbrush  (up  to  Vers  3.7)  and PC
  252. Paintbrush Plus (up to Vers 1.65)
  253.  
  254. The  bitmap character fonts are stored  in a particularly simple format.
  255. The format of these characters is as follows:
  256.  
  257.  
  258. Header
  259.  
  260. font width         byte                0xA0 + character width  (in pixels)
  261. font height        byte                character height  (in pixels)
  262.  
  263. Character Width Table
  264.  
  265. char widths        (256 bytes)         each char's width + 1 pixel of kerning
  266.  
  267. Character Images
  268.  
  269. (remainder of the file)                starts at char 0  (Null)
  270.  
  271. The  characters  are  stored in ASCII order  and  as  many as 256 may be
  272. provided.  Each character is left justified  in the character block, all
  273. characters take up the same number of bytes.
  274.  
  275. Bytes  are organized as N strings, where each string is one scan line of
  276. the character.
  277.  
  278. For  example, each character in a 5x7 font requires 7 bytes. A 9x14 font
  279. uses  28 bytes per character (stored two  bytes per scan line in 14 sets
  280. of  2  byte  packets). Custom fonts may  be  any  size up to the current
  281. maximum  of  10K bytes allowed for a font  file. There is a maximum of 4
  282. bytes per scan line.
  283.  
  284. Sample "C" Routines
  285.  
  286. The  following is a simple set of C subroutines to read data from a .PCX
  287. file.
  288.  
  289. /* This procedure reads one encoded block from the image file and stores a
  290. count and data byte.
  291.  
  292. Return result:  0 = valid data stored, EOF = out of data in file */
  293.  
  294. encget(pbyt, pcnt, fid)
  295. int *pbyt;        /* where to place data */
  296. int *pcnt;        /* where to place count */
  297. FILE *fid;        /* image file handle */
  298. {
  299. int i;
  300.         *pcnt = 1;        /* assume a "run" length of one */
  301.         if (EOF == (i = getc(fid)))
  302.                 return (EOF);
  303.         if (0xC0 == (0xC0 & i))
  304.                 {
  305.                 *pcnt = 0x3F & i;
  306.                 if (EOF == (i = getc(fid)))
  307.                         return (EOF);
  308.                 }
  309.         *pbyt = i;
  310.         return (0);
  311. }
  312. /* Here's a program fragment using encget.  This reads an entire file and
  313. stores it in a (large) buffer, pointed to by the variable "bufr". "fp" is
  314. the file pointer for the image */
  315.  
  316. int i;
  317. long l, lsize;
  318.      lsize = (long )hdr.BytesPerLine * hdr.Nplanes * (1 + hdr.Ymax - hdr.Ymin);
  319.      for (l = 0; l < lsize; )             /* increment by cnt below */
  320.                 {
  321.                 if (EOF == encget(&chr, &cnt, fp))
  322.                         break;
  323.                 for (i = 0; i < cnt; i++)
  324.                         *bufr++ = chr;
  325.                 l += cnt;
  326.                 }
  327.  
  328. The following is a set of C subroutines to write data to a .PCX file.
  329.  
  330. /* Subroutine for writing an encoded byte pair (or single byte if it
  331. doesn't encode) to a file. It returns the count of bytes written, 0 if error */
  332.  
  333. encput(byt, cnt, fid)
  334. unsigned char byt, cnt;
  335. FILE *fid;
  336. {
  337.   if (cnt) {
  338.         if ((cnt == 1) && (0xC0 != (0xC0 & byt)))
  339.                 {
  340.                 if (EOF == putc((int )byt, fid))
  341.                         return(0);     /* disk write error (probably full) */
  342.                 return(1);
  343.                 }
  344.         else
  345.                 {
  346.                 if (EOF == putc((int )0xC0 | cnt, fid))
  347.                         return (0);      /* disk write error */
  348.                 if (EOF == putc((int )byt, fid))
  349.                         return (0);      /* disk write error */
  350.                 return (2);
  351.                 }
  352.         }
  353.    return (0);
  354. }
  355.  
  356. /* This subroutine encodes one scanline and writes it to a file.
  357. It returns number of bytes written into outBuff, 0 if failed. */
  358.  
  359. encLine(inBuff, inLen, fp)
  360. unsigned char *inBuff;    /* pointer to scanline data */
  361. int inLen;                        /* length of raw scanline in bytes */
  362. FILE *fp;                        /* file to be written to */
  363. {
  364. unsigned char this, last;
  365. int srcIndex, i;
  366. register int total;
  367. register unsigned char runCount;     /* max single runlength is 63 */
  368.   total = 0;
  369.   runCount = 1;
  370.   last = *(inBuff);
  371.  
  372. /* Find the pixel dimensions of the image by calculating
  373. [XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1].
  374. Then calculate how many bytes are in a "run" */
  375.  
  376.   for (srcIndex = 1; srcIndex < inLen; srcIndex++)
  377.         {
  378.         this = *(++inBuff);
  379.         if (this == last)     /* There is a "run" in the data, encode it */
  380.                 {
  381.                 runCount++;
  382.                 if (runCount == 63)
  383.                         {
  384.                         if (! (i = encput(last, runCount, fp)))
  385.                                 return (0);
  386.                         total += i;
  387.                         runCount = 0;
  388.                         }
  389.                 }
  390.         else                /* No "run"  -  this != last */
  391.                 {
  392.                 if (runCount)
  393.                         {
  394.                         if (! (i = encput(last, runCount, fp)))
  395.                                 return(0);
  396.                         total += i;
  397.                         }
  398.                 last = this;
  399.                 runCount = 1;
  400.                 }
  401.         }        /* endloop */
  402.   if (runCount)        /* finish up */
  403.         {
  404.         if (! (i = encput(last, runCount, fp)))
  405.                 return (0);
  406.         return (total + i);
  407.         }
  408.   return (total);
  409. }
  410.  
  411. FRIEZE Technical Information
  412.  
  413. General FRIEZE Information
  414.  
  415. FRIEZE  is a memory-resident utility that allows you to capture and save
  416. graphic images from other programs. You can then bring these images into
  417. PC Paintbrush for editing and enhancement.
  418.  
  419. FRIEZE 7.10 and later can be removed from memory (this can return you up
  420. to  90K  of DOS RAM, depending  on your configuration). To remove FRIEZE
  421. from  memory,  change directories to  your paintbrush directory and type
  422. the word "FRIEZE".
  423.  
  424. 7.00 and Later FRIEZE
  425.  
  426. The FRIEZE command line format is:
  427.  
  428. FRIEZE {PD} {Xn[aarr]} {flags} {video} {hres} {vres} {vnum}
  429. Where:
  430. {PD}        Printer driver filename (without the .PDV extension)
  431. {Xn[aarr]}
  432.                 X=S for Serial Printer, P for Parallel Printer, D for disk file.
  433.                         (file is always named FRIEZE.PRN)
  434.                 n = port number
  435.                 aa = Two digit hex code for which return bits cause
  436.                          an abort (optional)
  437.                 rr = Two digit hex code for which return bits cause
  438.                         a retry (optional)
  439.                 NOTE:  These codes represent return values from serial or
  440.                        parallel port  BIOS calls.  For values see and IBM
  441.                        BIOS reference (such as Ray Duncan's Advanced MS-DOS
  442.                        Programming).
  443. {flags}Four digit hex code
  444.         First Digit controls Length Flag
  445.         Second Digit controls Width Flag
  446.                 Third Digit controls Mode Flag
  447.                 Fourth Digit controls BIOS Flag
  448.                         0 - None
  449.                         1 - Dual Monitor Present
  450.                         2 - Use internal (true) B/W palette for dithering
  451.                                 2 color images
  452.                         4 - Capture palette along with screen IN VGA ONLY
  453.                                 Frieze 8.08 & up ONLY)
  454.  
  455. NOTE:  The length, width and mode flags are printer driver specific. See
  456. PRINTERS.DAT on disk 1 (or Setup Disk) for correct use. In general width
  457. flag  of 1 means wide carriage, and  0 means standard width. Length flag
  458. of 0 and mode flag of 0 means use default printer driver settings.
  459.  
  460. If  you need to use more than one  BIOS flag option, add the needed flag
  461. values and use the sum as the flag value.
  462.  
  463. {video}       Video driver combination, where the leading digit signifies the
  464.                 high level video driver and the rest signifies the low
  465.                 level video driver
  466.                 Example = 1EGA - uses DRIVE1 and EGA.DEV
  467. {hres}        Horizontal resolution of the desired graphics mode
  468. {vres}        Vertical resolution of the desired graphics mode
  469. {vnum}        Hardware specific parameter (usually number of color planes)
  470.  
  471. Note:  The last four parameters can be obtained from the CARDS.DAT file,
  472. in your PC Paintbrush product directory.
  473.  
  474.  
  475. FRIEZE Function Calls
  476.  
  477. FRIEZE  is  operated  using  software  interrupt  number  10h (the video
  478. interrupt call).
  479.  
  480. To  make a FRIEZE function call, load  75 (decimal) into the AH register
  481. and  the function number into the CL  register, then either load AL with
  482. the  function argument or load ES and BX with a segment and offset which
  483. point  to  the  function argument. Do an  int  10h. FRIEZE will return a
  484. result code number in AX. All other registers are preserved. In general,
  485. a  result  code  of 0 means  success  and  other values indicate errors.
  486. However,  function  20  (get Frieze  Version)  behaves  differently; see
  487. below.
  488. No.      Definition         Arguments
  489. 0        Reserved
  490. 1        Load Window
  491.                             ES:BX - string  (filename to read from)
  492. 2        Save Window
  493.                             ES:BX - string  (filename to write to)
  494. 3        Reserved
  495. 4        Reserved
  496. 6        Reserved
  497. 7        Set Window Size
  498.                             ES:BX - 4 element word vector of window settings:
  499.                             Xmin, Ymin, Xmax, Ymax
  500. 8        Reserved
  501. 9        Set Patterns
  502.                             ES:BX - 16 element vector of byte values
  503.                             containing the screen-to-printer color                                          correspondence
  504. 10        Get Patterns
  505.                             ES:BX - room for 16 bytes as above
  506. 11        Set Mode
  507. 12,13,14  Reserved
  508. 15        Get Window
  509.                             ES:BX - room for 4 words of the current window
  510.                             settings
  511. 16         Set Print Options
  512.                             ES:BX - character string of printer options.
  513.                             Same format as for the FRIEZE command.
  514. 17, 18, 19        Reserved
  515. 20        Get FRIEZE Version.
  516.                             AH gets the whole number portion and AL gets the
  517.                             decimal portion of the version number.  (eg. for
  518.                             Freize vesion 7.41, AH will contain 7 and AL will
  519.                             contain 41.  If AH =0, you are calling a pre-7.0
  520.                             version of FRIEZE).
  521. 21        Set Parameters
  522.                             ES:BX points to an 8 word table  (16 bytes) of
  523.                             parameter settings: TopMargin, LeftMargin,
  524.                             HSize,VSize, Quality/Draft Mode, PrintHres,
  525.                             PrintVres, Reserved.
  526.                             Margins and sizes are specified in hundredths
  527.                             of inches.
  528.                                     Q/D mode parameter values:
  529.                                     0 - draft print mode
  530.                                     1 - quality print mode
  531.                                     Print resolutions are specified in DPI.
  532.                             Any parameter which should be left unchanged may
  533.                             be filled with a (-1) (0FFFF hex).  The reserved
  534.                             settings should be filled with a (-1).
  535. 22        Get Parameters
  536.                             ES:BX points to an 8 word table (16 bytes) where
  537.                             parameter settings are held.
  538. 23        Get Printer Res
  539.                             ES:BX points to a 12 word table (24 bytes) that
  540.                             holds six printer resolution pairs.
  541. 24        Reserved (versions 8.00 & up)
  542.  
  543. FRIEZE Error Codes
  544.  
  545. When  FRIEZE  is called using interrupt 10  hex, it will return an error
  546. code  in the AX register. A value of zero shows that there was no error.
  547. A  nonzero  result  means  there was  an  error.  These  error codes are
  548. explained below.
  549.  
  550.  0        No Error
  551.  1        Printout was stopped by user with the ESC key
  552.  2        Reserved
  553.  3        File read error
  554.  4        File write error
  555.  5        File not found
  556.  6        Invalid Header - not an image, wrong screen mode
  557.  7        File close error
  558.  8        Disk error - usually drive door open
  559.  9        Printer error - printer is off or out of paper
  560. 10        Invalid command - CL was set to call a nonexistent  FRIEZE function
  561. 11        Can't create file - write protect tab or disk is full
  562. 12        Wrong video mode - FRIEZE cannot capture text screens.
  563.  
  564. Technical Reference Manual
  565.  
  566. Including information for:
  567. Publisher's Paintbrushr
  568. PC Paintbrush IVTM
  569. PC Paintbrush IV PlusTM
  570. PC Paintbrush PlusTM
  571. PC Paintbrushr
  572. FRIEZETM Graphics
  573. PaintbrushTM
  574. Revision 5
  575.  
  576. ZSoft Corporation
  577. 450 Franklin Rd. Suite 100
  578. Marietta, GA  30067
  579. (404) 428-0008
  580. (404) 427-1150 Fax
  581. (404) 427-1045 BBS
  582.  
  583. Copyright c 1985, 1987, 1988, 1990, 1991, ZSoft Corporation
  584. All Rights Reserved
  585.  
  586.  
  587.  
  588.